package com.project.myPackage.controller;

import com.project.myPackage.common.R;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.*;
import java.util.*;

/**
 * 文件上传控制器
 */
@RestController
@RequestMapping("/")
@Slf4j
public class UploadController {

    @Value("${server.port}")
    private String downloadPath = "";

    /**
     * 文件上传接口
     */
    @PostMapping("/upload")
    public R<Object> upload(MultipartFile[] files) {
        List<String> pictures = new ArrayList<>();
        List<String> videoLink = new ArrayList<>();
        List<String> documents = new ArrayList<>();

        downloadPath = ServletUriComponentsBuilder.fromCurrentContextPath().toUriString();

        // 获取 static/upload 路径
        File path = new File(System.getProperty("user.dir"));
        if (!path.exists()) {
            path = new File("");
        }

        File uploadDir = new File(path.getAbsolutePath(), "/src/main/resources/static/upload/");
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }

        for (MultipartFile file : files) {
            log.info(file.toString());

            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || originalFilename.isEmpty()) {
                return R.error("上传文件名不能为空");
            }

            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = UUID.randomUUID() + suffix;

            File dest = new File(uploadDir, fileName);

            try {
                String contentType = file.getContentType();
                file.transferTo(dest);

                String downPath = downloadPath + "/download/" + fileName;
                log.info("后端地址：{}", downPath);

                if (contentType == null) {
                    return R.error("不支持的文件类型");
                }

                if (contentType.startsWith("image/")) {
                    pictures.add(downPath);
                } else if (contentType.startsWith("video/")) {
                    videoLink.add(downPath);
                } else if (isDocumentType(contentType)) {
                    documents.add(downPath);
                } else {
                    return R.error("不支持的文件类型: " + contentType);
                }

            } catch (IOException e) {
                log.error("文件上传失败", e);
                return R.error("文件上传失败：" + e.getMessage());
            }
        }

        UploadDto uploadDto = new UploadDto();
        uploadDto.setPictures(pictures);
        uploadDto.setVideoLink(videoLink);
        uploadDto.setDocuments(documents);

        return R.success(uploadDto);
    }


    private boolean isDocumentType(String contentType) {
        return contentType != null && (
                contentType.startsWith("application/pdf") ||
                        contentType.startsWith("application/msword") ||
                        contentType.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml.document") ||
                        contentType.startsWith("text/plain") ||
                        contentType.startsWith("application/vnd.ms-excel") ||
                        contentType.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
    }

    /**
     * 文件下载接口
     */
    @GetMapping("/download/{name}")
    public void download(@PathVariable String name, HttpServletResponse response) {
        try {
            // 获取 static/upload 目录
            File path = new File(System.getProperty("user.dir"));
            File uploadDir = new File(path.getAbsolutePath(), "/src/main/resources/static/upload/");
            File file = new File(uploadDir, name);

            if (!file.exists()) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.setContentType("text/plain;charset=UTF-8");
                response.getWriter().write("文件不存在");
                return;
            }

            String contentType = Files.probeContentType(file.toPath());
            if (contentType == null || !contentType.startsWith("image/")) {
                contentType = "application/octet-stream";
            }

            response.setContentType(contentType);

            try (InputStream in = new FileInputStream(file);
                 ServletOutputStream out = response.getOutputStream()) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
            }

        } catch (ClientAbortException e) {
            log.warn("客户端中止了连接: {}", e.getMessage());
        } catch (IOException e) {
            log.error("文件下载失败", e);
            try {
                response.setContentType("text/plain;charset=UTF-8");
                response.getWriter().write("文件下载失败：" + e.getMessage());
            } catch (IOException ex) {
                log.error("写入响应失败", ex);
            }
        }
    }

    /**
     * 根据文件名获取Content-Type
     */
    private String getContentType(String fileName) {
        if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (fileName.endsWith(".png")) {
            return "image/png";
        } else if (fileName.endsWith(".gif")) {
            return "image/gif";
        } else if (fileName.endsWith(".mp4")) {
            return "video/mp4";
        } else if (fileName.endsWith(".avi")) {
            return "video/x-msvideo";
        } else if (fileName.endsWith(".mov")) {
            return "video/quicktime";
        } else {
            return "application/octet-stream"; // 默认类型
        }
    }
}

@Data
class UploadDto implements Serializable {
    private static final long serialVersionUID = 1L;
    private List<String> pictures;
    private List<String> videoLink;
    private List<String> documents;
}
